package ex55.mm.flow.impound.quote.common.rdsdb;

import ex55.mm.flow.impound.quote.common.kit.CastKit;
import ex55.mm.flow.impound.quote.common.kit.Warning;
import org.jooq.Field;
import org.jooq.Record;
import org.springframework.lang.Nullable;

import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class ValuesBuilder {
    private final Map<Field, Object> values = new HashMap<>();

    //
    public static ValuesBuilder ignoreNull(Record record) {
        ValuesBuilder builder = new ValuesBuilder();
        for (Field<?> field : record.fields()) {
            Object value = record.get(field);
            if (value != null) {
                builder.values.put(field, value);
            }
        }
        return builder;
    }

    public <T> ValuesBuilder setIgnoreNull(Field<T> field, @Nullable T value) {
        if (value == null) {
            return this;
        }
        return set(field, value);
    }

    public ValuesBuilder setIgnoreNull(Field<String> field, @Nullable Enum value) {
        if (value == null) {
            return this;
        }
        return set(field, value);
    }

    public ValuesBuilder setIgnoreNull(Field<Timestamp> field, @Nullable Date value) {
        if (value == null) {
            return this;
        }
        return set(field, value);
    }

    public ValuesBuilder setIgnoreNull(Field<Timestamp> field, @Nullable Timestamp value) {
        if (value == null) {
            return this;
        }
        return set(field, value);
    }

    public <T> ValuesBuilder setIgnoreNull(Field<T> field, @Nullable Field<T> value) {
        if (value == null) {
            return this;
        }
        return set(field, value);
    }

    private void checkNullable(Field<?> field, @Nullable Object value) {
        if (!field.getDataType().nullable() && value == null) {
            throw Warning.newCommonError("field:" + field.getName() + " set can not null");
        }
    }

    /////
    public <T> ValuesBuilder set(Field<T> field, @Nullable T value) {
        checkNullable(field, value);
        if (value == null) {
            values.put(field, null);
            return this;
        }
        values.put(field, value);
        return this;
    }

    public ValuesBuilder set(Field<String> field, @Nullable Enum value) {
        checkNullable(field, value);
        if (value == null) {
            values.put(field, null);
            return this;
        }
        values.put(field, CastKit.string(value));
        return this;
    }

    public ValuesBuilder set(Field<Timestamp> field, @Nullable Date value) {
        checkNullable(field, value);
        if (value == null) {
            values.put(field, null);
            return this;
        }
        values.put(field, CastKit.timestamp(value));
        return this;
    }

    public ValuesBuilder set(Field<Timestamp> field, @Nullable Timestamp value) {
        checkNullable(field, value);
        if (value == null) {
            values.put(field, null);
            return this;
        }
        values.put(field, CastKit.timestamp(value));
        return this;
    }

    public <T> ValuesBuilder set(Field<T> field, @Nullable Field<T> value) {
        checkNullable(field, value);
        if (value == null) {
            values.put(field, null);
            return this;
        }
        values.put(field, value);
        return this;
    }


    public static ValuesBuilder v() {
        return new ValuesBuilder();
    }


    public Map<Field, Object> values() {
        return values;
    }

}
